
public class LinkedList
{
	LinkedListNode head;
	private int size;

	private class LinkedListNode
	{
		Memory data;
		LinkedListNode next;
		
		/**
		 * Creates a LinkedList node with a Memory data member
		 * @param data the Memory
		 */
		public LinkedListNode(Memory data)
		{
			this.data = data;
			this.next = null;
		}
	}
	
	/**
	 * Creates a LinkedList object with head = null
	 */
	public LinkedList()
	{
		head = null;
	}
	
	/**
	 * Inserts a Memory object into the LinkedList
	 * @param data the Memory to insert
	 */
	public void insert(Memory data)
	{
		LinkedListNode node = new LinkedListNode(data);
		node.next = head;
		head = node;
		size++;
	}
	
	/**
	 * Searches for a Memory object
	 * @param data the object to look for
	 * @return the object if found, null otherwise
	 */
	public Memory find(Memory data)
	{
		LinkedListNode node = head;
		while (node != null)
		{
			if (node.data.equals(data))
				return node.data;
			node = node.next;
		}
		return null;
	}
	
	/**
	 * Removes an object from the LinkedList
	 * @param size the size of Memory to delete
	 * @return the Memory deleted
	 */
	public Memory delete(int size)
	{
		LinkedListNode node = head;
	
		if (node == null)
			return null;
		
		if (head.data.size() == size) // delete the head
		{
			Memory m = head.data;
			head = head.next;
			size--;
			return m;
		}
		
		while (node.next != null)
		{
			if (node.next.data.size() == size) // delete next
			{
				Memory m = node.next.data;
				node.next = node.next.next;
				size--;
				return m;
			}
			node = node.next;
		}
		
		return null;
	}
	
	/**
	 * Delete a Memory object from the LinkedList
	 * @param m the object to delete
	 * @return the object deleted if found, null otherwise
	 */
	public Memory delete(Memory m)
	{
		LinkedListNode node = head;
		
		if (node == null)
			return null;
		
		if (head.data.size() == m.size()) // delete the head
		{
			head = head.next;
			size--;
			return m;
		}
		
		while (node.next != null)
		{
			if (node.next.data.size() == m.size()) // delete next
			{
				node.next = node.next.next;
				size--;
				return m;
			}
			node = node.next;
		}
		
		return null;
	}
	
	/**
	 * Finds the first Memory object greater than or equal to a specific size
	 * @param number the size to search with
	 * @return the Memory >= size, null if it could not find one
	 */
	public Memory findFirstGreaterThan(int number)
	{
		LinkedListNode node = head;
		while (node != null)
		{
			if (number <= node.data.size())
				return node.data;
			node = node.next;
		}
		
		return null;
	}
	
	/**
	 * Checks to see if a certain index is null or has a Memory object
	 * @param index the index to check
	 * @return true if there is a Memory object at that index, false otherwise
	 */
	public boolean hasIndex(int index)
	{
		if (index >= size)
			return false;
		
		LinkedListNode current = head;

		for (int i = 0; i < index; i++)
		{
			if (current == null)
				return false;
		}
		return true;
	}
	
	/**
	 * Gets the object associated with the specific inde
	 * @param index the index to check
	 * @return the object found
	 */
	public Memory getIndex(int index)
	{
		LinkedListNode current = head;
		if (index == 0)
		{
			if (current != null)
				return current.data;
			return null;
		}
		
		for (int i = 0; i < index; i++)
		{
			if (current == null)
				return null;
			current = current.next;
		}
		
		if (current != null)
			return current.data;
		return null;
	}
	
	/**
	 * Gets the number of elements in the list
	 * @return the size
	 */
	public int size()
	{
		return size;
	}
	
	/**
	 * Creates a String representation of the LinkedList
	 * @return the String
	 */
	public String toString()
	{
		String s = "";
		if (size == 0)
			return s;
		
		LinkedListNode node = head;
		while (node != null)
		{
			s += node.data.toString() + " ";
			node = node.next;
		}
		return s;
	}
}
